<template>
  <div class="graph-index" :id="graphId">
    <div class="chart-palette">
      <!-- 文件上传 -->
      <input type="file" ref="upload" accept=".erm" @change="executorListchange" class="file_executor" style="display: none;">
      <!-- 工具栏 -->
      <ul class="tool-items">
        <p v-for="(item, index) in toolItems" :key="index" class="tool-item" ref="toolItem" :title="item.title">
          <i :class="item.iconClass" aria-hidden="true"></i>
        </p>
        <p class="tool-item" :class="{'actived':onOneToMany}" style="cursor: pointer;" title="一对多关系" @click="oneToMany">
          <svg t="1619076747834" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1896" width="16" height="16">
            <path d="M952.066611 601.9072l60.0064-60.0064a42.24 42.24 0 0 0 0-59.8016l-60.0064-60.0064a42.2912 42.2912 0 0 0-72.192 29.9008V460.8H563.663411V153.6h316.2112v8.8064a42.2912 42.2912 0 0 0 72.192 29.9008l60.0064-60.0064a42.24 42.24 0 0 0 0-59.8016L952.066611 12.4928a42.2912 42.2912 0 0 0-72.192 29.9008V51.2H512.463411a51.2 51.2 0 0 0-51.2 51.2v358.4H191.081011a102.4 102.4 0 1 0 0 102.4H461.263411v358.4a51.2 51.2 0 0 0 51.2 51.2h367.4112v8.8064a42.2912 42.2912 0 0 0 72.192 29.9008l60.0064-60.0064a42.24 42.24 0 0 0 0-59.8016l-60.0064-60.0064a42.2912 42.2912 0 0 0-72.192 29.9008V870.4H563.663411v-307.2h316.2112v8.8064a42.2912 42.2912 0 0 0 72.192 29.9008z" fill="#697890" p-id="1897"></path>
          </svg>
        </p>

        <!-- <p class="tool-item" style="cursor: pointer;" title="多对多关系">
          <svg t="1619076904526" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2317" width="16" height="16">
            <path d="M952.169011 601.9072l60.0064-60.0064a42.24 42.24 0 0 0 0-59.8016l-60.0064-60.0064a42.2912 42.2912 0 0 0-72.192 29.9008V460.8H691.765811V405.3504l194.56-194.56 6.144 6.144a42.2912 42.2912 0 0 0 72.192-29.952V102.4a42.24 42.24 0 0 0-42.2912-42.2912h-84.7872a42.2912 42.2912 0 0 0-29.952 72.192l6.0416 5.9392-194.56 194.56h-212.992l-153.088-153.088A102.4 102.4 0 1 0 154.165811 256a100.2496 100.2496 0 0 0 26.112-3.7888L333.365811 405.3504V460.8H191.081011a102.4 102.4 0 1 0 0 102.4H333.365811v55.808l-152.9344 152.832A100.8128 100.8128 0 0 0 154.165811 768a102.4 102.4 0 1 0 102.4 102.4 101.3248 101.3248 0 0 0-3.7376-26.0096L406.121011 691.2h212.992l185.7536 185.7536-6.1952 6.1952a42.2912 42.2912 0 0 0 29.9008 72.192h84.8896a42.2912 42.2912 0 0 0 42.2912-42.2912v-85.0432a42.2912 42.2912 0 0 0-72.192-29.9008l-5.9904 5.9904L691.765811 618.8544V563.2h188.16v8.96a42.2912 42.2912 0 0 0 72.2432 29.7472zM589.365811 460.8v128H435.765811V435.2h153.6z" fill="#697890" p-id="2318"></path>
          </svg>
        </p> -->

      </ul>

      <div class="bottom-tools">
        <div class="item" :class="{'actived':showToolName=='table'||showToolName=='table-column'}" title="表格" @click="tableDetailType='attribute';showToolName=='table'||showToolName=='table-column'?showToolName='':showToolName='table'">
          <i class="fa fa-list-alt"></i>
        </div>
        <div class="item" :class="{'actived':showToolName=='note'}" title="笔记" @click="showToolName=='note'?showToolName='':showToolName='note'">
          <i class="fa fa-file-text"></i>
        </div>
        <div class="item" :class="{'actived':showToolName=='tools'}" title="工具" @click="showToolName=='tools'?showToolName='':showToolName='tools'">
          <i class="fa fa-gears"></i>
        </div>
        <div class="item" :class="{'actived':showToolName=='info'}" title="信息" @click="showToolName=='info'?showToolName='':showToolName='info'">
          <i class="fa fa-info-circle"></i>
        </div>
      </div>
    </div>

    <div :id="graphId+'-canvas'" style="position: relative;z-index: 9;background-color: white; width: 100%; height: 100%">
      <div class="diagram-div" style="background-color: white; width: 100%; height: 100%">
        <graph-editor @remove-cells='removeCells' class="graphEditor" ref="graphEditor" style="overflow: auto;width: 100%;height: 100%;" />
      </div>
    </div>

    <div class="left-pane" :style="{'width':leftToolPaneWidth+'px'}" v-show="showToolName">

      <div class="note-list tool-plane" v-show="showToolName=='note'">
        <div class="title">
          <i style="line-height: 1rem;cursor: pointer;" class="fa fa-chevron-left" aria-hidden="true" @click="showToolName=''"></i>
          <span style="flex: 1;text-align: center;line-height: 1rem;">笔记</span>
        </div>
        <div style="flex: 1;height: 0;overflow-y: auto;">
          <div class="node-item" v-for="(node,index1) in noteDataArray" :index="index1" style="-webkit-user-select: text;display: inline-flex;width: 300px;">
            <textarea v-show="false" :value='node.text'></textarea>
            <div>{{node.text}}</div>
          </div>
        </div>
      </div>

      <!-- 表 list -->
      <div class="table-list tool-plane" v-show="showToolName=='table'" style="-webkit-user-select: text;">
        <div class="title">
          <i style="line-height: 1rem;cursor: pointer;" class="fa fa-chevron-left" aria-hidden="true" @click="showToolName=''"></i>
          <span style="flex: 1;text-align: center;line-height: 1rem;">表</span>
        </div>
        <div style="flex: 1;height: 0;overflow-y: auto;">
          <div class="table-item" v-for="(table,index1) in tableDataArray" :index="index1" style="display: inline-flex;width: 300px;">
            <i style="margin-right: 10px;" class="fa fa-map-marker" @click.stop="toTableLocation(table)" title="定位"></i>
            <span @click="toTable(table)">{{table.name}}/{{table.physical_name}}</span>
          </div>
        </div>
      </div>
      <!-- 表详情 -->
      <div class="colum-list tool-plane" v-show="showToolName=='table-column'">
        <div class="title">
          <i style="line-height: 1rem;cursor: pointer;" class="fa fa-chevron-left" aria-hidden="true" @click="showToolName='table'"></i>
          <span style="flex: 1;text-align: center;line-height: 1rem;">
            {{editTableInfo.logical_name}}/{{editTableInfo.physical_name}}
            <i style="line-height: 1rem;cursor: pointer;" class="fa fa-edit" aria-hidden="true" @click="tableDetailType='edit-table'"></i>
          </span>
        </div>

        <div style="flex: 1;height: 0;overflow-y: auto;display: flex;">
          <div class="table-detail-left">
            <div class="item" :class="{'actived':tableDetailType=='attribute'}" @click="tableDetailType='attribute'">属性</div>
            <div class="item" :class="{'actived':tableDetailType=='data'}" @click="tableDetailType='data'">数据</div>
            <div class="item" :class="{'actived':tableDetailType=='unique'}" @click="tableDetailType='unique'">约束</div>
            <div class="item" :class="{'actived':tableDetailType=='remark'}" @click="tableDetailType='remark'">描述</div>
            <div class="item" :class="{'actived':tableDetailType=='edit'||tableDetailType=='edit-table'}" v-show="tableDetailType=='edit' || tableDetailType=='edit-table'">编辑</div>
          </div>
          <div class="table-detail-rigth table-attribute" v-show="tableDetailType=='attribute'">
            <div class="colum-item" style="font-weight: bold;">
              <div style="flex: 3;">字段</div>
              <div style="flex: 3;">注释</div>
              <div style="width: 100px;">类型</div>
              <div style="width: 60px;text-align: center;">非空</div>
            </div>
            <div style="-webkit-user-select: text;" class="colum-item" :class="{'actived':rightMenu.from==index1}" v-for="(colum,index1) in showTableColums" :index="index1" @click="choiceColum(index1)" @dblclick="editColum(index1)">
              <div :index="index1" :style="{'color':colum.primary_key?'#e67e22':colum.foreign_key?'#1abc9c':''}" style="flex: 3;">
                {{colum.physical_name}}
              </div>
              <div :index="index1" :style="{'color':colum.primary_key?'#e67e22':colum.foreign_key?'#1abc9c':''}" style="flex: 3;">
                {{colum.logical_name}}
              </div>
              <div :index="index1" :style="{'color':colum.primary_key?'#e67e22':colum.foreign_key?'#1abc9c':''}" style="width: 100px;">
                {{getDetailType(colum)}}
              </div>
              <div :index="index1" :style="{'color':colum.primary_key?'#e67e22':colum.foreign_key?'#1abc9c':''}" style="width: 60px;">
                <input :index="index1" type="checkbox" disabled :checked="colum.not_null">
              </div>
            </div>
          </div>
          <!-- 编辑 字段 -->
          <div class="table-detail-rigth edit" v-show="tableDetailType=='edit'">
            <div style="display: flex;padding: 4px 10px;background: #ffec9e;color: #d35400;">
              <span style="flex:1">编辑完请,点击右侧勾勾确认！</span>
              <i class="fa fa-close" style="margin-right:10px;cursor: pointer;line-height: 1rem;" @click="tableDetailType='attribute'"></i>
              <i class="fa fa-check" style="cursor: pointer;line-height: 1rem;" @click="editSure()"></i>
            </div>
            <div class="item">
              <label>名称</label>
              <span>：</span>
              <div style="position: relative; flex: 1 1 0%;border: 1px rgba(0,0,0,0.1) solid;" v-if="!editColumDetail.foreign_key">
                <input style="width: calc(100% - 30px); position: absolute; left: 1px; border: none; outline: none;" v-model="editColumDetail.physical_name" class="flex1" />
                <i v-show="!showWordSelect" @click="showWordSelect=true" style="float: right;line-height: 21px;cursor: pointer;margin-right: 6px;" class="fa fa-angle-down" aria-hidden="true"></i>
                <i v-show="showWordSelect" @click="showWordSelect=false" style="float: right;line-height: 21px;cursor: pointer;margin-right: 6px;" class="fa fa-angle-up" aria-hidden="true"></i>
              </div>
              <input v-if="editColumDetail.foreign_key" v-model="editColumDetail.physical_name" class="flex1" />
            </div>
            <div v-show="showWordSelect" class="item word-select">
              <div class="word" v-for="(dictionary,index) in dictionarysSelect" :key="index" :value="dictionary.id" @click="choiceWord(dictionary.wordId)">
                {{dictionary.physical_name}}：{{dictionary.logical_name}} {{dictionary.typeDetail}}
              </div>
            </div>
            <div class="item">
              <label>注释</label>
              <span>：</span>
              <input v-model="editColumDetail.logical_name" class="flex1" />
            </div>
            <div class="item">
              <label>类型</label>
              <span>：</span>
              <select :disabled='editColumDetail.foreign_key' v-model="editColumDetail.type" class="flex1" style="width:100%;">
                <option :selected='editColumDetail.type === type' :value="type" v-for="(type,index) in columStype" :key="index">{{type}}</option>
              </select>
            </div>
            <div class="item">
              <label>长度</label>
              <span>：</span>
              <input :disabled='editColumDetail.lengthDisable||editColumDetail.foreign_key' type="number" v-model="editColumDetail.length" class="flex1">
            </div>
            <div class="item">
              <label>小数</label>
              <span>：</span>
              <input :disabled='editColumDetail.decimalDisable||editColumDetail.foreign_key' type="number" v-model="editColumDetail.decimal" class="flex1">
            </div>
            <div class="item">
              <label>无符号</label>
              <span>：</span>
              <input :disabled='editColumDetail.foreign_key' type="checkbox" v-model="editColumDetail.unsigned">
            </div>
            <div class="item" v-show="!editColumDetail.foreign_key">
              <label>主键</label>
              <span>：</span>
              <input type="checkbox" v-model="editColumDetail.primary_key">
            </div>
            <div class="item" v-show="editColumDetail.foreign_key">
              <label>外键</label>
              <span>：</span>
              <input disabled type="checkbox" checked="checked">
            </div>
            <div class="item">
              <label>唯一</label>
              <span>：</span>
              <input type="checkbox" v-model="editColumDetail.unique_key">
            </div>
            <div class="item">
              <label>非空</label>
              <span>：</span>
              <input v-show='!editColumDetail.primary_key' type="checkbox" v-model="editColumDetail.not_null">
              <input v-show='editColumDetail.primary_key' disabled type="checkbox" checked="checked">
            </div>
            <div class="item">
              <label>描述</label>
              <span>：</span>
              <textarea style="webkit-user-select: text;" v-model="editColumDetail.description" class="flex1" />
            </div>
          </div>
          <!-- 编辑 表 -->
          <div class="table-detail-rigth edit" v-show="tableDetailType=='edit-table'">
            <div style="display: flex;padding: 4px 10px;background: #ffec9e;color: #d35400;">
              <span style="flex:1">编辑完请,点击右侧勾勾确认！</span>
              <i class="fa fa-close" style="margin-right:10px;cursor: pointer;line-height: 1rem;" @click="tableDetailType='attribute'"></i>
              <i class="fa fa-check" style="cursor: pointer;line-height: 1rem;" @click="editTableSure()"></i>
            </div>
            <div class="item">
              <label>名称：</label>
              <input v-model="editTableInfo.physical_name" class="flex1" />
            </div>
            <div class="item">
              <label>注释：</label>
              <input v-model="editTableInfo.logical_name" class="flex1" />
            </div>
          </div>
          <!-- 数据 -->
          <div class="table-detail-rigth" v-show="tableDetailType=='data'">
            <div style="margin:20px">
              预计功能
              <br>
              1.数据预览
              <br>
              2.一键造数据
              <br>
              努力开发中...
            </div>
          </div>
          <!-- 约束 -->
          <div class="table-detail-rigth" v-show="tableDetailType=='unique'">
            <div style="margin:20px">
              预计功能
              <br>
              1.查看、修改主键
              <br>
              2.查看、修改外键
              <br>
              3.查看、修改唯一约束
              <br>
              努力开发中...
            </div>
          </div>
          <!-- 描述 -->
          <div class="table-detail-rigth" v-show="tableDetailType=='remark'">
            <div style="display: flex;padding: 4px 10px;background: #ffec9e;color: #d35400;">
              <span style="flex:1">编辑完请,点击右侧勾勾确认！</span>
              <i class="fa fa-close" style="margin-right:10px;cursor: pointer;line-height: 1rem;" @click="tableDetailType='attribute'"></i>
              <i class="fa fa-check" style="cursor: pointer;line-height: 1rem;" @click="editTableSure(true)"></i>
            </div>
            <textarea class="table-remark" v-model="editTableInfo.description" placeholder='请输入描述'>

            </textarea>
          </div>
        </div>

      </div>

      <!-- 插件工具-->
      <div class="tool-list tool-plane" v-show="showToolName=='tools'">
        <div class="title">
          <i style="line-height: 1rem;cursor: pointer;" class="fa fa-chevron-left" aria-hidden="true" @click="showToolName=''"></i>
          <span style="flex: 1;text-align: center;line-height: 1rem;">工具</span>
        </div>
        <div style="flex: 1;height: 0;overflow-y: auto;">

        </div>
      </div>

      <!-- erm 配置信息-->
      <div class="info-plane tool-plane" v-show="showToolName=='info'">
        <div class="title">
          <i style="line-height: 1rem;cursor: pointer;" class="fa fa-chevron-left" aria-hidden="true" @click="showToolName=''"></i>
          <span style="flex: 1;text-align: center;line-height: 1rem;">配置</span>
        </div>
        <div style="flex: 1;height: 0;overflow-y: auto;display: flex;flex-direction: column;">
          <div class="tab">
            <span :class="{'actived':projectInfo.showTabIndex==0}" @click="projectInfo.showTabIndex=0">项目信息</span>
            <span :class="{'actived':projectInfo.showTabIndex==1}" @click="projectInfo.showTabIndex=1">数据库</span>
          </div>
          <div style="flex: 1;height: 0;overflow-y: auto;" v-if="projectInfo.showTabIndex==0">
            <div class="colum-item" style="font-weight: bold;">
              <div style="flex: 1;">键</div>
              <div style="flex: 1;">值</div>
            </div>
            <div class="colum-item value" v-for="(colum,index1) in projectInfo.property" :index="index1">
              <div style="flex: 1;">{{colum.name}}
              </div>
              <div style="flex: 1;">{{colum.value}}
              </div>
            </div>
          </div>

          <div style="flex: 1;height: 0;overflow-y: auto;" v-if="projectInfo.showTabIndex==1">
            <div class="colum-item" style="font-weight: bold;">
              服务器:
            </div>
            <div class="colum-item value">
              <div style="flex: 1;">
                地址:
              </div>
              <div style="flex: 3;">
                <input placeholder="" />
              </div>
            </div>
            <div class="colum-item value">
              <div style="flex: 1;">
                端口:
              </div>
              <div style="flex: 3;">
                <input placeholder="" type="number" />
              </div>
            </div>
            <div class="colum-item value">
              <div style="flex: 1;">
                数据库:
              </div>
              <div style="flex: 3;">
                <input placeholder="" />
              </div>
            </div>
            <div class="colum-item value">
              <div style="flex: 1;">
                表名:
              </div>
              <div style="flex: 3;">
                <input placeholder="" />
              </div>
            </div>

            <div class="colum-item" style="font-weight: bold;">
              认证:
            </div>
            <div class="colum-item value">
              <div style="flex: 1;">
                账号:
              </div>
              <div style="flex: 3;">
                <input placeholder="" />
              </div>
            </div>
            <div class="colum-item value">
              <div style="flex: 1;">
                密码:
              </div>
              <div style="flex: 3;">
                <input placeholder="" type="password" />
              </div>
            </div>

            <div class="colum-item" style="margin: 10px 0;">
              <div class="button">测试连接</div>
              <div class="button" style="margin-left: 20px;">连接</div>
            </div>
          </div>
        </div>
      </div>

      <div class="resize resize-div" v-show="showToolName"></div>
    </div>
    <div class="loading" v-show="showLoading" :style="{'opacity':showLoadingOpacity}">
      <div class="icon">
        <i class="fa-solid fa-circle-notch "></i>
        <p>正在载入</p>
      </div>
    </div>

    <div class='find-modal' v-show="showFindModal">
      <input @keyup.enter="findNextKey" :id="'findInput'+graphId" v-model="findKey" placeholder="搜索" @input="findPositionIndex=-1" />
      <i class="fa fa-chevron-up" title="查找上一个" @click="findBeforeKey"></i>
      <i class="fa fa-chevron-down" title="查找下一个" @click="findNextKey"></i>
      <i class="fa fa-close" title="关闭" @click="findPositionIndex=-1;showFindModal=false"></i>
    </div>

    <!-- 表属性右键菜单 -->
    <div class="rigth-menu" v-show="rightMenu.show" :style="{'left':rightMenu.left,'top':rightMenu.top}">
      <div class="item" @click="addCloum">
        <i class="fa fa-plus-square" />
        <span>新增字段</span>
      </div>
      <div class="item" @click="editColum(rightMenu.columIndex)" v-show="rightMenu.from!=undefined && rightMenu.from>=0">
        <i class="fa fa-edit" />
        <span>编辑字段</span>
      </div>
      <div @click="removeColum(rightMenu.from)" class="item" v-show="rightMenu.from!=undefined && rightMenu.from>=0">
        <i class="fa fa-window-close-o" />
        <span>删除字段</span>
      </div>
    </div>

    <div class="edit-note-modal" v-show="editNoteModal.show" :style="{'left':editNoteModal.left+'px','top':editNoteModal.top+'px'}">
      <div class="title">
        <span class="title-move">编辑笔记</span>
        <i class="fa fa-close" style="margin-right:10px;cursor: pointer;" @click="editNoteModal.show=false"></i>
        <i class="fa fa-check" style="cursor: pointer;" @click="saveEditNote()"></i>
      </div>
      <textarea style="webkit-user-select: text;" v-model="editNoteModal.text"></textarea>
    </div>

    <div class="message" :style="{'opacity':message.opacity}" v-show="message.show">鼠标移动到表中心后拖拽</div>
  </div>

</template>

<script>
var ipcRenderer;
if (window.require) {
  ipcRenderer = window.require("electron").ipcRenderer;
}
import Swal from "sweetalert2";
import mxgraph from "./mxgraph";
const {
  mxToolbar,
  mxGraphModel,
  mxGraph,
  mxCell,
  mxGeometry,
  mxEvent,
  mxUtils,
  mxCellState,
  mxGraphHandler,
  mxPanningHandler,
  mxImage,
  mxEllipse,
  mxConnectionConstraint,
  mxPoint,
} = mxgraph;
import ermUtils from "./ermUtil.js";
import { toolItems } from "./toolbarItems.js";
import GraphEditor from "./editor.vue";
export default {
  components: {
    GraphEditor,
  },
  props: ["graphId"],
  name: "graphIndex",
  data() {
    return {
      onOneToMany: false,
      message: {
        show: false,
        opacity: 1
      },
      columStype: [
        "bigint",
        "bigint(n)",
        "binary",
        "binary(n)",
        "bit",
        "bit(n)",
        "blob",
        "boolean",
        "char",
        "char(n)",
        "date",
        "datetime",
        "decimal",
        "decimal(10,4)",
        "decimal(19,4)",
        "decimal(p)",
        "decimal(p,s)",
        "double",
        "double(m,d)",
        "enum",
        "float",
        "float(m,d)",
        "float(p)",
        "int",
        "int(n)",
        "longblob",
        "longtext",
        "mediumblob",
        "mediumint",
        "mediumint(n)",
        "mediumtext",
        "numeric",
        "numeric(p)",
        "numeric(p,s)",
        "real",
        "real(m,d)",
        "smallint",
        "smallint(n)",
        "text",
        "time",
        "timestamp",
        "tinyblob",
        "tinyint",
        "tinyint(n)",
        "tinytext",
        "varbinary(n)",
        "varchar(n)",
        "year(2)",
        "year(4)",
      ], //字段类型
      tableDetailType: "attribute",
      findKey: "",
      findPositionIndex: -1, //查找位置
      showFindModal: false,
      leftToolPaneWidth: 450, //工具栏
      projectInfo: {
        showTabIndex: 0,
        property: [], //erm 的信息
      },
      showLoadingOpacity: 0, //加载框透明度
      showLoading: false, //加载框显示状态
      showTableColums: [], //列表展示表的字段
      showToolName: "", //当前展示的工具
      //绘图相关 -start
      toolItems: toolItems, //左侧拖拽单元
      graph: null, //画板
      tableDataArray: [], //需要绘制的表格列表
      linkDataArray: [], //连线列表
      noteDataArray: [], //笔记列表
      //绘图相关 -end
      tableCellIdMap: new Map(), //表格 id关联
      noteCellIdMap: new Map(), //笔记 id关联
      cellIdToTableDataIndexMap: new Map(), //cell id关联 tableDataArray index
      cellIdToNoteDataIndexMap: new Map(), //cell id关联 noteDataArray index
      editTableIndex: "", //当前编辑的表索引
      editColumDetail: {}, //当前编辑的字段内容
      referencedColumnsMap: new Map(),//这里存着全部外键,用于查询这个主键是否存在外键  key：主键id，value关联的外键表字段{tableIndex,columIndex}
      editTableInfo: {
        //当前编辑的表格信息
        physical_name: "",
        logical_name: "",
        description: ""
      },
      xmlFile: {
        xml: "", //文件内容
        name: "", //文件名
      }, //文件缓存在这里
      rightMenu: {
        //编辑字段的弹窗菜单属性和 编辑字段索引
        from: -1, //点击的是哪个字段索引 用于标记选中
        columIndex: 0, //当前编辑的字段索引
        show: false,
        left: 0,
        top: 0,
      }, //右键菜单
      editNoteModal: {
        //编辑笔记的窗体属性
        show: false,
        left: 0,
        top: 0,
        index: "", //noteDataArry索引
        text: "",
      },
      tableIndexMap: new Map(), //key:表id，value:erm里面的索引
      noteIndexMap: new Map(), //key:笔记id，value:erm里面的索引 第几个节点
      dictionarysIndexMap: new Map(), //key:字典id，value:erm里面字典的索引
      dictionarys: [],//字典
      dictionarysSelect: [],//筛选后的字典
      showWordSelect: false,//显示字典选择
    };
  },
  watch: {
    "editColumDetail.physical_name"(n, o) {
      if (!this.showWordSelect) return
      if (n === '') {
        this.dictionarysSelect = JSON.parse(JSON.stringify(this.dictionarys));
      } else {
        this.dictionarysSelect.splice(0, this.dictionarysSelect.length)
        for (let i = 0; i < this.dictionarys.length; i++) {
          if (this.dictionarys[i].logical_name.indexOf(n) >= 0) {
            this.dictionarysSelect.push(this.dictionarys[i])
          }
        }
      }
    },
    "editColumDetail.type"(n, o) {
      if (/\d/.test(n)) {
        this.editColumDetail.lengthDisable = true;
        this.editColumDetail.decimalDisable = true;
        return
      }
      if (n.indexOf(',') > 0) {
        this.editColumDetail.lengthDisable = false;
        this.editColumDetail.decimalDisable = false;
        return
      }
      if (n.indexOf('(') > 0) {
        this.editColumDetail.decimalDisable = true;
        this.editColumDetail.lengthDisable = false;
        return
      }
      this.editColumDetail.lengthDisable = true;
      this.editColumDetail.decimalDisable = true;
    },
    "editNoteModal.text"(n, o) {
      if (!this.editNoteModal.show) {
        return;
      }
      this.$emit("change-file-status", true);
    },
  },
  methods: {
    //编辑表 remarkTag是否保存描述
    editTableSure(remarkTag) {
      // if (this.tableDetailType !== "edit-table"|| ) {
      //   return;
      // }
      this.tableDataArray[this.editTableIndex].name = this.editTableInfo.logical_name;
      this.tableDataArray[this.editTableIndex].physical_name = this.editTableInfo.physical_name;
      this.tableDataArray[this.editTableIndex].description = this.editTableInfo.description;
      this.$emit("change-file-status", true);
      var c = document.querySelector(
        ".table-" + this.tableDataArray[this.editTableIndex].id + " .title"
      );
      c.innerHTML =
        this.editTableInfo.logical_name +
        "/" +
        this.editTableInfo.physical_name;
      let index = this.tableIndexMap.get(this.tableDataArray[this.editTableIndex].id).index
      let tableDom = this.xmlFile.xml.querySelector('contents').children[index]
      tableDom.querySelector("logical_name").innerHTML = this.editTableInfo.logical_name
      tableDom.querySelector("physical_name").innerHTML = this.editTableInfo.physical_name
      if (remarkTag) {
        tableDom.querySelector("description").innerHTML = this.editTableInfo.description
      }
      this.tableDetailType = "attribute"
    },
    //开启一对多
    oneToMany() {
      this.onOneToMany = !this.onOneToMany
      if (this.onOneToMany) {
        this.message.show = true
        this.message.opacity = 1
        setTimeout(() => {
          this.message.opacity = 0
          setTimeout(() => {
            this.message.show = false
          }, 500);
        }, 2500);
      }
      this.graph.setConnectable(this.onOneToMany);
    },
    //选择字典
    choiceWord(wordId) {
      this.showWordSelect = false;
      let word = this.dictionarys[this.dictionarysIndexMap.get(wordId)];
      this.editColumDetail.length = word.length
      this.editColumDetail.decimal = word.decimal
      this.editColumDetail.array = word.array
      this.editColumDetail.array_dimension = word.array_dimension
      this.editColumDetail.unsigned = word.unsigned
      this.editColumDetail.args = word.args
      this.editColumDetail.description = word.description
      this.editColumDetail.logical_name = word.logical_name
      this.editColumDetail.physical_name = word.physical_name
      this.editColumDetail.type = word.type
      this.editColumDetail.word_id = wordId
    },
    //保存编辑笔记内容
    saveEditNote() {
      this.editNoteModal.show = false;
      let note = this.xmlFile.xml.querySelector('contents').children[this.noteIndexMap.get(this.editNoteModal.id).index]
      note.querySelector('text').innerHTML = this.editNoteModal.text
      this.$emit("change-file-status", true);
      this.loadXml(this.xmlFile.xml, true)
    },
    //修改字段
    editSure() {
      this.tableDetailType = "attribute";
      if (this.editColumDetail.add) {

        let hasWord = false;
        let items = this.tableDataArray[this.editTableIndex].items;
        this.editColumDetail.id = new Date().getTime();
        let objE = document.createElement("div");
        objE.innerHTML = this.getColumHtml(this.editColumDetail);
        document
          .querySelector(
            ".table-" + this.tableDataArray[this.editTableIndex].id + " .items"
          )
          .append(objE.childNodes[0]);
        items.push(this.editColumDetail);
        this.rightMenu.columIndex = items.length - 1;
        hasWord = this.editColumDetail.word_id != undefined || this.editColumDetail.word_id != '';
        if (hasWord) {
          let word = this.dictionarys[this.dictionarysIndexMap.get(this.editColumDetail.word_id)];
          if (!word || this.editColumDetail.length != word.length
            || this.editColumDetail.decimal != word.decimal
            || this.editColumDetail.array != word.array
            || this.editColumDetail.array_dimension != word.array_dimension
            || this.editColumDetail.unsigned != word.unsigned
            || this.editColumDetail.args != word.args
            || this.editColumDetail.description != word.description
            || this.editColumDetail.logical_name != word.logical_name
            || this.editColumDetail.physical_name != word.physical_name
            || this.editColumDetail.type != word.type) {
            hasWord = false
          }
        }

        if (!hasWord) {
          //增加word 字典
          this.editColumDetail.word_id = new Date().getTime()
          var wordDom = this.xmlFile.xml.createElement("dom");
          wordDom.innerHTML = ermUtils.creatWordContent(this.editColumDetail)
          this.xmlFile.xml.querySelector("dictionary").append(wordDom.children[0])
        }

        //增加字段
        var columDom = this.xmlFile.xml.createElement("dom");
        columDom.innerHTML = ermUtils.creatColumContent(this.editColumDetail)
        let index = this.tableIndexMap.get(this.tableDataArray[this.editTableIndex].id).index
        this.xmlFile.xml.querySelector('contents').children[index].querySelector("columns").append(columDom.children[0])

        this.showTableColums = items
      }
      this.sendChangeStatus();
    },
    //发送修改状态
    sendChangeStatus() {
      this.$emit("change-file-status", true);
      if (
        this.rightMenu.columIndex == undefined ||
        this.editColumDetail.id == undefined
      ) {
        return;
      }

      let tableId = this.tableDataArray[this.editTableIndex].id;
      let tableIndex = this.tableIndexMap.get(tableId).index;
      //当前编辑的字段id
      let columId = this.tableDataArray[this.editTableIndex].items[this.rightMenu.columIndex].id

      //修改数组内容
      this.showTableColums[this.rightMenu.columIndex].physical_name = this.editColumDetail.physical_name
      this.showTableColums[this.rightMenu.columIndex].logical_name = this.editColumDetail.logical_name
      this.showTableColums[this.rightMenu.columIndex].not_null = this.editColumDetail.not_null
      this.showTableColums[this.rightMenu.columIndex].type = this.editColumDetail.type
      this.showTableColums[this.rightMenu.columIndex].primary_key = this.editColumDetail.primary_key
      this.showTableColums[this.rightMenu.columIndex].foreign_key = this.editColumDetail.foreign_key

      //修改xml内容
      if (this.editColumDetail.foreign_key) {
        let columIndex = this.tableIndexMap.get(tableId).columnsIndexMap.get(columId).index;
        let table = this.xmlFile.xml.querySelector("contents").children[tableIndex];
        let colum = table.querySelector("columns").children[columIndex];

        colum.querySelector("logical_name").innerHTML = this.editColumDetail.logical_name;
        colum.querySelector("physical_name").innerHTML = this.editColumDetail.physical_name;
        colum.querySelector("not_null").innerHTML = this.editColumDetail.not_null;
        colum.querySelector("description").innerHTML = this.editColumDetail.description;
      } else {
        if (this.tableIndexMap.get(tableId).columnsIndexMap.get(columId)) {

          let columIndex = this.tableIndexMap.get(tableId).columnsIndexMap.get(columId).index;
          let table = this.xmlFile.xml.querySelector("contents").children[tableIndex];
          let colum = table.querySelector("columns").children[columIndex];

          if (this.tableIndexMap.get(tableId).columnsIndexMap.get(columId)) {
            let wordIndex = this.tableIndexMap.get(tableId).columnsIndexMap.get(columId).wordIndex;
            let word = this.xmlFile.xml.querySelector("dictionary").children[wordIndex];
            word.querySelector("logical_name").innerHTML = this.editColumDetail.logical_name;
            word.querySelector("physical_name").innerHTML = this.editColumDetail.physical_name;
            word.querySelector("description").innerHTML = this.editColumDetail.description;
            word.querySelector("length").innerHTML = this.editColumDetail.length;
            word.querySelector("decimal").innerHTML = this.editColumDetail.decimal;
            word.querySelector("array").innerHTML = this.editColumDetail.array;
            word.querySelector("array_dimension").innerHTML = this.editColumDetail.array_dimension;
            word.querySelector("unsigned").innerHTML = this.editColumDetail.unsigned;
            word.querySelector("zerofill").innerHTML = this.editColumDetail.zerofill;
            word.querySelector("binary").innerHTML = this.editColumDetail.binary;
            word.querySelector("args").innerHTML = this.editColumDetail.args;
            //word.querySelector("char_semantics").innerHTML = this.editColumDetail.char_semantics;
            word.querySelector("type").innerHTML = this.editColumDetail.type;
          }
          colum.querySelector("not_null").innerHTML = this.editColumDetail.not_null;
          colum.querySelector("primary_key").innerHTML = this.editColumDetail.primary_key;
          colum.querySelector("unique_key").innerHTML = this.editColumDetail.unique_key;
          colum.querySelector("auto_increment").innerHTML = this.editColumDetail.auto_increment;
        }
      }

      this.loadXml(this.xmlFile.xml, true)


    },
    //获取字段完整类型
    getDetailType(colum) {
      if (!colum.type) {
        return ''
      }
      if (/\d/.test(colum.type)) {
        return colum.type;
      }
      if (colum.type.indexOf(',') > 0) {
        let type = colum.type.substring(0, colum.type.indexOf('('));
        return type + "(" + colum.length + "," + colum.decimal + ")";
      }
      if (colum.type.indexOf('(') > 0) {
        let type = colum.type.substring(0, colum.type.indexOf('('));
        return type + "(" + colum.length + ")";
      }
      return colum.type;
    },
    //删除一个字段
    removeColum(index) {
      let _index = index
      let _this = this
      Swal.fire({
        title:
          '确认删除"' +
          this.tableDataArray[this.editTableIndex].items[index].physical_name +
          '"吗?',
        showDenyButton: true,
        showCancelButton: true,
        showConfirmButton: false,
        denyButtonText: `确认`,
        cancelButtonText: `取消`,
      }).then((result) => {
        if (result.isDenied) {
          let table = _this.tableDataArray[_this.editTableIndex]
          let column = table.items[_index]
          let columIndex = _this.tableIndexMap.get(table.id).columnsIndexMap.get(column.id).index
          let index = _this.tableIndexMap.get(table.id).index
          let tableDom = _this.xmlFile.xml.querySelector('contents').children[index]
          let columDom = tableDom.querySelector("columns").children[columIndex]
          //这是一个外键 需要删除外键关联
          if (column.foreign_key) {
            let relationId = columDom.querySelector('relation').innerHTML
            let relations = tableDom.querySelector("connections").children
            for (let i = 0; i < relations.length; i++) {
              if (relations[i].querySelector('id').innerHTML == relationId) {
                relations[i].parentNode.removeChild(relations[i])
                break
              }
            }
          } else if (column.primary_key && _this.referencedColumnsMap.get(table.id + '-' + column.id)) {
            //找到外键内容
            let fk = _this.referencedColumnsMap.get(table.id + '-' + column.id)

            //外键表索引
            let tableDom = _this.xmlFile.xml.querySelector('contents').children[fk.tableIndex]
            let fkColumn = tableDom.querySelector('columns').children[fk.columnIndex]
            //移除外键
            fkColumn.parentNode.removeChild(fkColumn)
            //删除线条
            let relations = tableDom.querySelector("connections").children
            for (let i = 0; i < relations.length; i++) {
              if (relations[i].querySelector('id').innerHTML == fk.relationId) {
                relations[i].parentNode.removeChild(relations[i])
                break
              }
            }
          }
          columDom.parentNode.removeChild(columDom)
          _this.tableDataArray[_this.editTableIndex].items.splice(_index, 1);
          _this.showTableColums = _this.tableDataArray[_this.editTableIndex].items

          _this.loadXml(_this.xmlFile.xml, true)
        }
      });
    },
    //新增一个字段--未添加到列表
    addCloum() {
      let newColum = {
        description: "",
        foreign_key: false,
        logical_name: "新字段",
        not_null: false,
        physical_name: "new colum",
        primary_key: false,
        type: "varchar(n)",
        length: '255',
        decimal: 'null',
        tunique_keyype: false,
        add: true,
      };
      this.editColumDetail = newColum;
      this.rightMenu.show = false;
      this.tableDetailType = "edit";
    },
    //添加一个表
    addNewTable(cell, toolItem, height, width, x, y) {
      var table = {
        id: new Date().getTime(),
        height: height,
        width: width,
        x: x,
        y: y,
        name: "表名",
        physical_name: "new_table",
        description: '',
        items: [],
      };
      this.tableDataArray.push(table);

      toolItem.html = (index) => this.getTableCell(table);

      let newCell = this.instanceCell(cell, toolItem, x, y);
      this.tableCellIdMap.set(table.id, newCell);

      this.cellIdToTableDataIndexMap.set(
        newCell.id,
        this.tableDataArray.length - 1
      );
      this.$emit("change-file-status", true);
      var tableDom = this.xmlFile.xml.createElement("dom");
      tableDom.innerHTML = ermUtils.creatTableContent(table.id, table.name, table.physical_name, width, height, x, y);
      this.xmlFile.xml.querySelector("contents").append(tableDom.children[0])

      this.loadXml(this.xmlFile.xml, true)
    },
    //添加一个笔记
    addNewNote(cell, toolItem, height, width, x, y) {
      var note = {
        id: new Date().getTime(),
        x: x,
        y: y,
        width: width,
        height: height,
        text: "",
      };
      var tableDom = this.xmlFile.xml.createElement("dom");
      tableDom.innerHTML = ermUtils.creatNoteContent(note);
      this.xmlFile.xml.querySelector("contents").append(tableDom.children[0])
      this.$emit("change-file-status", true);
      this.loadXml(this.xmlFile.xml, true)
    },
    //编辑字段
    editColum(index) {
      if (index == undefined) {
        return;
      }
      this.rightMenu.show = false;
      this.tableDetailType = "edit";
      this.editColumDetail = JSON.parse(JSON.stringify(this.tableDataArray[this.editTableIndex].items[index]))
      this.editColumDetail.add = false
      if (this.editColumDetail.description) {
        var obj = eval("(" + this.editColumDetail.description + ")");
        this.editColumDetail.description = JSON.stringify(obj, null, 4);
      } else {
        this.editColumDetail.description = "";
      }
    },
    //选择文件
    choiceFile() {
      var inputObj = document.querySelector(
        "#" + this.graphId + " .file_executor"
      );
      inputObj.click();
    },
    //查找上一个
    findBeforeKey() {
      if (this.findPositionIndex - 1 < 0) {
        alert("已经找到头了");
        return;
      }
      for (
        this.findPositionIndex--;
        this.findPositionIndex >= 0;
        this.findPositionIndex--
      ) {
        var table = this.tableDataArray[this.findPositionIndex];
        if (
          table.physical_name
            .toLowerCase()
            .indexOf(this.findKey.toLowerCase()) >= 0 ||
          table.name.toLowerCase().indexOf(this.findKey.toLowerCase()) >= 0
        ) {
          this.toTableLocation(table);
          return;
        }
        for (var x = 0; x < table.items.length; x++) {
          var item = table.items[x];
          if (
            item.physical_name
              .toLowerCase()
              .indexOf(this.findKey.toLowerCase()) >= 0 ||
            item.logical_name
              .toLowerCase()
              .indexOf(this.findKey.toLowerCase()) >= 0
          ) {
            this.toTableLocation(table);
            return;
          }
        }
      }
      if (this.findPositionIndex <= 0) {
        alert("已经找到头了");
        return;
      }
    },
    //查找下一个
    findNextKey() {
      if (this.findPositionIndex + 1 >= this.tableDataArray.length) {
        alert("已经找到结尾了");
        return;
      }
      for (
        this.findPositionIndex++;
        this.findPositionIndex < this.tableDataArray.length;
        this.findPositionIndex++
      ) {
        var table = this.tableDataArray[this.findPositionIndex];
        if (
          table.physical_name
            .toLowerCase()
            .indexOf(this.findKey.toLowerCase()) >= 0 ||
          table.name.toLowerCase().indexOf(this.findKey.toLowerCase()) >= 0
        ) {
          this.toTableLocation(table);
          return;
        }
        for (var x = 0; x < table.items.length; x++) {
          var item = table.items[x];
          if (
            item.physical_name
              .toLowerCase()
              .indexOf(this.findKey.toLowerCase()) >= 0 ||
            item.logical_name
              .toLowerCase()
              .indexOf(this.findKey.toLowerCase()) >= 0
          ) {
            this.toTableLocation(table);
            // this.findPositionIndex++;
            return;
          }
        }
      }
      if (this.findPositionIndex >= this.tableDataArray.length) {
        alert("已经找到结尾了");
        return;
      }
    },
    //表格聚焦
    toTableLocation(table) {
      var cell = this.tableCellIdMap.get(table.id);
      if (cell) {
        this.graph.setSelectionCell(cell);
        var cell = this.tableCellIdMap.get(table.id);
        var diagramDiv = document.querySelector(
          "#" + this.graphId + " .diagram-div"
        );
        var graphContainer = document.querySelector(
          "#" + this.graphId + " .graphContainer"
        );
        var tableDiv = document.querySelector(
          "#" + this.graphId + " .graphContainer .table-" + table.id
        );
        var sc = this.graph.getView().getScale(); //获取当前的缩放比例

        graphContainer.scrollTop =
          (tableDiv.offsetTop - diagramDiv.offsetHeight / 2) * sc;
        graphContainer.scrollLeft =
          (tableDiv.offsetLeft - diagramDiv.offsetWidth / 2) * sc;
      } else {
        alert("您选择的图形不在画布中！");
      }
    },
    //获取表格内容
    toTable(table) {
      var cell = this.tableCellIdMap.get(table.id);
      if (cell) {
        this.graph.setSelectionCell(cell);
        var diagramDiv = document.querySelector(
          "#" + this.graphId + " .diagram-div"
        );
        var graphContainer = document.querySelector(
          "#" + this.graphId + " .graphContainer"
        );
        var tableDiv = document.querySelector(
          "#" + this.graphId + " .graphContainer .table-" + table.id
        );
        var sc = this.graph.getView().getScale(); //获取当前的缩放比例

        graphContainer.scrollTop =
          (tableDiv.offsetTop - diagramDiv.offsetHeight / 2) * sc;
        graphContainer.scrollLeft =
          (tableDiv.offsetLeft - diagramDiv.offsetWidth / 2) * sc;

        this.showTableColums = table.items;
        this.showToolName = "table-column";
        this.editTableIndex = this.cellIdToTableDataIndexMap.get(cell.id);
        if (table.description) {
          var obj = eval("(" + table.description + ")");
          this.editTableInfo.description = JSON.stringify(obj, null, 4);
        } else {
          this.editTableInfo.description = "";
        }
        this.tableDetailType = "attribute";
        this.editTableInfo.logical_name = table.name;
        this.editTableInfo.physical_name = table.physical_name;
      } else {
        alert("您选择的图形不在画布中！");
      }
    },
    //拖拽文件
    enentDrop(e) {
      e.stopPropagation();
      e.preventDefault(); //必填字段
      let fileData = e.dataTransfer.files;
      this.readFile(fileData[0]);
    },
    executorListchange() {
      var files = document.querySelector("#" + this.graphId + " .file_executor")
        .files;
      this.readFile(files[0]);
    },
    //读取文件
    readFile(file) {
      if (file.name.indexOf(".erm") != file.name.length - 4) {
        alert("不支持的文件格式");
        return;
      }
      var _this = this;
      this.showLoadingFun(true);
      var reader = new FileReader(); //新建一个FileReader
      reader.readAsText(file, "UTF-8"); //读取文件
      reader.onload = function (evt) {
        //读取完文件之后会回来这里
        var fileString = evt.target.result; // 读取文件内容
        var xmlDoc = null;
        if (window.DOMParser) {
          var parser = new DOMParser();
          xmlDoc = parser.parseFromString(fileString, "text/xml");
        } else {
          //IE
          xmlDoc = new ActiveXObject("Microsoft.XMLDOM");
          xmlDoc.async = "false";
          xmlDoc.loadXML(fileString);
        }

        _this.loadXml(xmlDoc);

        let savePath
        if (ipcRenderer) {
          savePath = JSON.parse(JSON.stringify(file.path))
          if (savePath) {
            savePath = savePath.replaceAll('\\', '/')
            savePath = savePath.substring(0, savePath.lastIndexOf('/'))
          }
        }

        _this.xmlFile = {
          xml: xmlDoc,
          name: file.name,
          path: savePath
        };


        _this.$emit("change-file-name", file.name);
      };
      document.querySelector("#" + this.graphId + " .file_executor").value = "";
    },
    //读取内容
    loadXml(xmlDoc, reload) {
      let _this = this;
      this.cellIdToTableDataIndexMap.clear();
      this.tableCellIdMap.clear();
      //this.showToolName = "";
      this.linkDataArray.splice(0, _this.linkDataArray.length);
      this.tableDataArray.splice(0, _this.tableDataArray.length);
      this.noteDataArray.splice(0, _this.noteDataArray.length);
      this.dictionarys.splice(0, _this.dictionarys.length);
      this.dictionarysSelect.splice(0, _this.dictionarysSelect.length);
      this.dictionarysIndexMap.clear();
      this.tableIndexMap.clear();
      this.referencedColumnsMap.clear();

      let tables = xmlDoc.querySelector("contents").children;
      let modelProperties = xmlDoc.querySelector("settings model_properties");
      let xmlDictionarys = xmlDoc.querySelector("dictionary").children;

      //获取项目信息
      ((properties) => {
        this.projectInfo.property.splice(0, this.projectInfo.property.length);
        if (properties) {
          var allPropertie = properties.querySelectorAll("model_property");
          for (var x = 0; x < allPropertie.length; x++) {
            var name = allPropertie[x].querySelector("name").innerHTML;
            var value = allPropertie[x].querySelector("value").innerHTML;
            this.projectInfo.property.push({
              value: value,
              name: name,
            });
          }
        }
      })(modelProperties);

      //全部字段
      for (let x = 0; x < xmlDictionarys.length; x++) {
        let id = xmlDictionarys[x].querySelector("id").innerHTML;
        this.dictionarysIndexMap.set(id, x);
        let word = xmlDictionarys[x];
        this.dictionarys.push({
          wordId: id,
          logical_name: word.querySelector("logical_name").innerHTML.substring(0, 10),
          physical_name: word.querySelector("physical_name").innerHTML,
          length: word.querySelector("length").innerHTML,
          decimal: word.querySelector("decimal").innerHTML,
          array_dimension: word.querySelector("array_dimension").innerHTML,
          unsigned: word.querySelector("unsigned").innerHTML,
          description: word.querySelector("description").innerHTML,
          type: word.querySelector("type").innerHTML,
          typeDetail: this.getDetailType({
            type: word.querySelector("type").innerHTML,
            decimal: word.querySelector("decimal").innerHTML,
            length: word.querySelector("length").innerHTML
          })
        })
      }
      //全部表
      for (let x = 0; x < tables.length; x++) {
        let table = tables[x];
        if (table.nodeName == "note") {
          let tm = {
            index: x
          };
          this.noteIndexMap.set(table.querySelector("id").innerHTML, tm);
          continue
        }
        if (table.nodeName == "table") {
          let columns = table.querySelector("columns").children;
          let columnsIndexMap = new Map();
          //整理表的字段
          for (let y = 0; y < columns.length; y++) {
            let wordId = columns[y].querySelector("word_id");
            let id = columns[y].querySelector("id").innerHTML;
            let wm = {
              index: y,
            };
            if (wordId) {
              //对应字典的索引
              wm.wordIndex = this.dictionarysIndexMap.get(wordId.innerHTML);
            }
            columnsIndexMap.set(id, wm);
          }
          let tm = {
            index: x,
            columnsIndexMap: columnsIndexMap,
          };
          this.tableIndexMap.set(table.querySelector("id").innerHTML, tm);
          continue
        }
      }
      this.dictionarys.sort(function (a, b) {
        return a.physical_name.charCodeAt(0) - b.physical_name.charCodeAt(0);
      })
      this.dictionarysSelect = JSON.parse(JSON.stringify(this.dictionarys));


      //开始构建表格
      for (let x = 0; x < tables.length; x++) {
        let table = tables[x];

        //全部字段
        let normalColumns = table.querySelectorAll("normal_column");
        //实体关系 connections
        let connections = table.querySelector("connections").children;
        //存关联到map方便获取
        let relationMap = new Map();
        for (let r = 0; r < connections.length; r++) {
          relationMap.set(
            connections[r].querySelector("id").innerHTML,
            connections[r]
          );
          let id = connections[r].querySelector("id");
          let source = connections[r].querySelector("source");
          let target = connections[r].querySelector("target");
          let child_cardinality = connections[r].querySelector(
            "child_cardinality"
          );
          let parent_cardinality = connections[r].querySelector(
            "parent_cardinality"
          );
          _this.linkDataArray.push({
            id: id ? id.innerHTML : "",
            from: source ? source.innerHTML : "",
            to: target ? target.innerHTML : "",
            text: parent_cardinality ? parent_cardinality.innerHTML : "",
            toText: child_cardinality ? child_cardinality.innerHTML : "",
          });
        }

        if (table.nodeName != "table") {
          if (table.nodeName == "note") {
            _this.noteDataArray.push({
              id: table.querySelector("id").innerHTML,
              x: table.querySelector("x").innerHTML,
              y: table.querySelector("y").innerHTML,
              width: table.querySelector("width").innerHTML,
              height: table.querySelector("height").innerHTML,
              text: table.querySelector("text").innerHTML,
            });
          }
          continue;
        }
        let items = [];

        //遍历字段
        for (let y = 0; y < normalColumns.length; y++) {
          let normalColumn = normalColumns[y];
          let word_id = normalColumn.querySelector("word_id");
          let colum_id = normalColumn.querySelector("id").innerHTML;
          let not_null = normalColumn.querySelector("not_null").innerHTML;
          let unique_key = normalColumn.querySelector("unique_key").innerHTML;
          let relation = normalColumn.querySelector("relation");
          let logicalName = normalColumn.querySelector("logical_name");
          let physicalName = normalColumn.querySelector("physical_name");
          let foreign_key = normalColumn.querySelector("foreign_key").innerHTML;
          let primary_key = normalColumn.querySelector("primary_key").innerHTML;
          if (word_id) {
            //表 从word获取表名称-因为normalColumn是外键外键的话只有id不知道名称，要去全部内容里获取
            let word = xmlDictionarys[this.dictionarysIndexMap.get(word_id.innerHTML)];
            let type = word.querySelector("type");
            let length = word.querySelector("length");
            let decimal = word.querySelector("decimal");
            let unsigned = word.querySelector("unsigned");
            let array_dimension = word.querySelector("array_dimension");
            let array = word.querySelector("array");
            let char_semantics = word.querySelector("array");
            let zerofill = word.querySelector("zerofill");
            let binary = word.querySelector("binary");
            let args = word.querySelector("args");
            items.push({
              id: colum_id,
              length: length ? length.innerHTML : '',
              decimal: decimal ? decimal.innerHTML : "",
              array: array ? array.innerHTML : "",
              array_dimension: array_dimension ? array_dimension.innerHTML : '',
              unsigned: unsigned ? unsigned.innerHTML : '',
              zerofill: zerofill ? zerofill.innerHTML : '',
              binary: binary ? binary.innerHTML : '',
              args: args ? args.innerHTML : '',
              char_semantics: char_semantics ? char_semantics.innerHTML : "",
              description: word.querySelector("description").innerHTML,
              logical_name: word.querySelector("logical_name").innerHTML,
              physical_name: word.querySelector("physical_name").innerHTML,
              unique_key: unique_key == "true",
              primary_key: primary_key == "true",
              foreign_key: false,
              type: type ? type.innerHTML : '',
              not_null: not_null == "true",
              word_id: word_id.innerHTML
            });
          } else if (relation) {
            //外键逻辑
            let logical_name = logicalName.innerHTML; //外键自己的注释
            let physical_name = physicalName.innerHTML; //外键自己的字段名
            let description = normalColumn.querySelector("description")
              .innerHTML; //外键自己的描述

            let r = relationMap.get(relation.innerHTML); //获取关系
            let source = r.querySelector("source").innerHTML; //外键的索引
            let referenced_column = normalColumn.querySelector(
              "referenced_column"
            ).innerHTML; //外键字段id
            let indexMap = this.tableIndexMap.get(source);
            let word =
              xmlDictionarys[
              indexMap.columnsIndexMap.get(referenced_column).wordIndex
              ];
            let type = word.querySelector("type");
            let length = word.querySelector("length");
            let decimal = word.querySelector("decimal");
            let unsigned = word.querySelector("unsigned");
            let array_dimension = word.querySelector("array_dimension");
            let array = word.querySelector("array");
            let char_semantics = word.querySelector("array");
            if (!logical_name) {
              logical_name = word.querySelector("logical_name");
            }
            if (!physical_name) {
              physical_name = word.querySelector("physical_name");
            }
            if (!description && word.querySelector("description")) {
              description = word.querySelector("description");
            }
            items.push({
              id: colum_id,
              logical_name: logical_name,
              physical_name: physical_name,
              foreign_key: foreign_key == "true",
              primary_key: false,
              type: type ? type.innerHTML : '',
              length: length ? length.innerHTML : '',
              decimal: decimal ? decimal.innerHTML : '',
              not_null: not_null == "true",
              description: description ? description.innerHTML : '',
              unsigned: unsigned ? unsigned.innerHTML : '',
              array_dimension: array_dimension ? array_dimension.innerHTML : '',
              array: array ? array.innerHTML : '',
              char_semantics: char_semantics ? char_semantics.innerHTML : '',
            });
            let key = source + '-' + referenced_column
            let val = {
              tableIndex: x,
              columnIndex: y,
              relationId: relation.innerHTML
            }
            this.referencedColumnsMap.set(key, val)
          }
        }
        _this.tableDataArray.push({
          id: table.querySelector("id").innerHTML,
          physical_name: table.querySelector("physical_name").innerHTML,
          name: table.querySelector("logical_name").innerHTML,
          x: table.querySelector("x").innerHTML,
          y: table.querySelector("y").innerHTML,
          width: table.querySelector("width").innerHTML,
          height: table.querySelector("height").innerHTML,
          description: table.querySelector("description").innerHTML,
          items: items,
        });
      }
      _this.init(reload);
    },
    //绘制内容
    init(reload) {
      this.graph.getModel().beginUpdate();
      try {
        var _this = this;
        _this.graph.removeCells(
          _this.graph.getChildVertices(_this.graph.getDefaultParent())
        );
        for (var x in _this.tableDataArray) {
          var table = _this.tableDataArray[x];
          var cell = _this.addCellToContainer(table);
          _this.tableCellIdMap.set(table.id, cell);
          _this.cellIdToTableDataIndexMap.set(cell.id, x);
        }

        for (var x in _this.noteDataArray) {
          var note = _this.noteDataArray[x];
          var cell = _this.addCellToContainer(note, "note");
          _this.tableCellIdMap.set(note.id, cell);
          _this.noteCellIdMap.set(note.id, cell);

          //  _this.noteCellIdMap.set(table.id, cell);
          _this.cellIdToNoteDataIndexMap.set(cell.id, x);
        }

        for (var x in _this.linkDataArray) {
          var source = _this.tableCellIdMap.get(_this.linkDataArray[x].from);
          var target = _this.tableCellIdMap.get(_this.linkDataArray[x].to);
          var e = this.graph.insertEdge(
            this.graph.getDefaultParent(),
            _this.linkDataArray[x].id,
            "",
            source,
            target,
            "endArrow=none;strokeColor=#dfe6e9;strokeWidth=1;rounded=0"
          );
          if (source.title != '表' || target.title != '表') {
            continue
          }

          //起点文字
          var sLabel = this.graph.insertVertex(
            e,
            null,
            _this.linkDataArray[x].text,
            -0.9,
            0,
            0,
            0,
            "labelBackgroundColor=#ffffff;fillColor=none;strokeColor=none"
          );
          sLabel.geometry.relative = true;
          //终点文字
          var eLabel = this.graph.insertVertex(
            e,
            null,
            _this.linkDataArray[x].toText,
            0.9,
            0,
            0,
            0,
            "labelBackgroundColor=#ffffff;fillColor=none;strokeColor=none"
          );
          eLabel.geometry.relative = true;
        }
      } finally {
        //_this.graph.zoomTo(0.8); //在缩放一半，否则是满屏状态，不好看
        _this.graph.getModel().endUpdate();
        _this.showLoadingFun(false);
        if (reload) { return }
        setTimeout(() => {
          var graphContainer = document.querySelector(
            "#" + this.graphId + " .graphContainer svg"
          );
          _this.showLoadingFun(false);
          if (!graphContainer) {
            return;
          }
          var x = parseInt(graphContainer.style.minWidth.replace("px", "")) / 3;
          var y =
            parseInt(graphContainer.style.minHeight.replace("px", "")) / 3;
          _this.graph.panGraph(-x, -y);
        }, 100);
      }
    },
    //获取绘制表内容
    addCellToContainer(table, type) {
      const parent = this.graph.getDefaultParent();
      var index = 0;
      if ("table" == type) {
        index = 0;
      } else if ("note" == type) {
        index = 1;
      }
      var x = JSON.parse(JSON.stringify(toolItems[index]));
      x.width = parseInt(table.width);
      x.height = parseInt(table.height);

      if (index == 0) {
        if (table.name) {
          x.html = (index) => this.getTableCell(table);
        }
      } else if (index == 1) {
        x.html = (index) => this.getNoteCell(table);
      }
      return this.instanceCell(
        null,
        x,
        parseInt(table.x),
        parseInt(table.y),
        table.id
      );
    },
    //获取笔记内容
    getNoteCell(note) {
      return `<div class="note note-` + note.id + `">${note.text}</div>`;
    },
    //获取表格画布内容
    getTableCell(table) {
      var items = "";
      for (var x in table.items) {
        items += this.getColumHtml(table.items[x]);
      }
      return (
        `<div class="table table-` +
        table.id +
        `" ><div class="table-info"><div class='title'>${table.name}/${table.physical_name}</div><div class='items'>` +
        items +
        `</div></div></div>`.replace(/[\r\n]/g, "")
      );
    },
    //获取属性列
    getColumHtml(colum) {
      var html;
      if (colum.primary_key) {
        html =
          `<div class="item colum-` +
          colum.id +
          `"><div style="width: 1rem;"><i class="fa fa-key" aria-hidden="true" style="color: #e67e22;margin-right: 5px;font-size: 0.6rem;"></i></div><div class="text" style="color: #e67e22;">${colum.logical_name}/${colum.physical_name}</div></div>`;
      } else if (colum.foreign_key) {
        html =
          `<div class="item colum-` +
          colum.id +
          `"><div style="width: 1rem;"><i class="fa fa-key" aria-hidden="true" style="color: #1abc9c;margin-right: 5px;font-size: 0.6rem;"></i></div><div class="text" style="color: #1abc9c;">${colum.logical_name}/${colum.physical_name}</div></div>`;
      } else {
        html =
          `<div class="item colum-` +
          colum.id +
          `"><div style="width: 1rem;"></div><div class="text">${colum.logical_name}/${colum.physical_name}</div></div>`;
      }
      return html;
    },
    //拖拽组件
    makeToolbarDraggable() {
      const toolItems = this.$refs.toolItem;
      if (!(toolItems instanceof Array)) {
        return;
      }
      toolItems.forEach((item, index) => {
        const toolItem = this.toolItems[index];
        const { height, width } = toolItem;
        // drop的处理函数
        const dropHandler = (graph, evt, cell, x, y) => {
          if (toolItem.title == "表") {
            this.addNewTable(cell, toolItem, height, width, x, y);
          } else {
            this.addNewNote(cell, toolItem, height, width, x, y);
          }
        };
        // 创建拖拽时的预览图形
        const createDragPreview = () => {
          const elt = document.createElement("div");
          elt.style.transition = `none`;
          elt.style.border = "2px dotted black";
          elt.style.width = `${width}px`;
          elt.style.height = `${height}px`;
          return elt;
        };
        // 获取拖放的对象
        const getDropTarget = (graph, x, y) => {
          const cell = graph.getCellAt(x, y);

          return this.R.propOr(null, "dropAble", cell) ? cell : null;
        };

        mxUtils.makeDraggable(
          item,
          this.graph,
          dropHandler,
          createDragPreview(index),
          0,
          0,
          false,
          true,
          true,
          getDropTarget
        );
      });
    },
    //绘制表
    instanceCell(dropCell, toolItem, x, y, id) {
      const drop = !this.R.isNil(dropCell);
      const styleObj = toolItem["style"] || {};
      const style = Object.keys(styleObj)
        .map((key) => `${key}=${styleObj[key]}`)
        .join(";");
      const realX = drop ? x - dropCell.geometry.x : x;
      const realY = drop ? y - dropCell.geometry.y : y;
      const { height, width } = toolItem;
      const parent = drop ? dropCell : this.graph.getDefaultParent();
      const isHtml = Object.is("1", toolItem["style"]["html"]);
      const tmpIndex = Date.now();
      const value = isHtml ? toolItem["html"](tmpIndex) : null;

      this.graph.getModel().beginUpdate();
      try {
        const cell = this.graph.insertVertex(
          parent,
          id,
          value,
          realX,
          realY,
          width,
          height,
          style
        );

        cell["title"] = toolItem["title"];
        cell["dropAble"] = toolItem["dropAble"];
        //cell['constraints'] = toolItem['constraints']
        this.$nextTick(() => {
          const createdCallback = toolItem["created"];
          if (createdCallback instanceof Function) {
            createdCallback(this.graph, cell, tmpIndex);
          }
        });
        return cell;
      } finally {
        this.graph.getModel().endUpdate();
      }
    },
    //初始化线条样式
    initConnectStyle() {
      this.graph.setConnectable(false);

      this.graph.setAllowDanglingEdges(false);
      this.graph.setConnectableEdges(false);
      this.graph.setDisconnectOnMove(true);
      this.graph.setMultigraph(false);

      const style = this.graph.getStylesheet().getDefaultEdgeStyle();

      style["rounded"] = "0";
      style["strokeColor"] = "#dfe6e9";
      style["strokeWidth"] = "1";
      this.graph.connectionHandler.createEdgeState = function () {
        const edge = this.graph.createEdge();
        return new mxCellState(
          this.graph.view,
          edge,
          this.graph.getCellStyle(edge)
        );
      };

      //创建关系
      this.graph.connectionHandler.addListener(mxEvent.CONNECT, (sender, evt) => {
        let edge = evt.getProperty('cell');
        let haveKey = false
        let source = edge.source
        let target = edge.target
        let sourceId, targetId
        let relationId = new Date().getTime()

        if (source.title != '表' || target.title != '表') {
          let targetIndex, targetDom
          //找到来源 id
          if (source.title == '表') {
            let dataIndex = this.cellIdToTableDataIndexMap.get(source.id)
            sourceId = this.tableDataArray[dataIndex].id
          } else {
            let dataIndex = this.cellIdToNoteDataIndexMap.get(source.id)
            sourceId = this.noteDataArray[dataIndex].id
          }

          //找到目标 id
          if (target.title == '表') {
            let dataIndex = this.cellIdToTableDataIndexMap.get(target.id)
            targetId = this.tableDataArray[dataIndex].id
            targetIndex = this.tableIndexMap.get(targetId).index
          } else {
            let dataIndex = this.cellIdToNoteDataIndexMap.get(target.id)
            targetId = this.noteDataArray[dataIndex].id
            targetIndex = this.noteIndexMap.get(targetId).index
          }

          //在目标上添加关系
          targetDom = this.xmlFile.xml.querySelector('contents').children[targetIndex]
          let edgeDom = this.xmlFile.xml.createElement("dom");
          edgeDom.innerHTML = ermUtils.creatCommentEdgeContent({
            id: relationId,
            sourceId: sourceId,
            targetId: targetId
          })
          targetDom.querySelector('connections').append(edgeDom.children[0])
          this.loadXml(this.xmlFile.xml, true)
          return
        }

        let sourceDataIndex = this.cellIdToTableDataIndexMap.get(source.id)
        sourceId = this.tableDataArray[sourceDataIndex].id

        let targetDataIndex = this.cellIdToTableDataIndexMap.get(target.id)
        targetId = this.tableDataArray[targetDataIndex].id

        let tableIndex = this.tableIndexMap.get(sourceId).index
        let table = this.xmlFile.xml.querySelector('contents').children[tableIndex]

        let targetTableIndex = this.tableIndexMap.get(targetId).index
        let targetTable = this.xmlFile.xml.querySelector('contents').children[targetTableIndex]

        //来到来源主键
        let columns = table.querySelector('columns').children
        for (let i = 0; i < columns.length; i++) {
          let pk = columns[i].querySelector('primary_key');
          if (pk && pk.innerHTML == 'true') {
            haveKey = true
            //找到主键对应的word
            let word = this.dictionarys[this.dictionarysIndexMap.get(columns[i].querySelector('word_id').innerHTML)]

            //增加字段
            let columDom = this.xmlFile.xml.createElement("dom");

            columDom.innerHTML = ermUtils.creatColumContent({
              id: new Date().getTime(),
              description: '',
              unique_key_name: '',
              logical_name: word.logical_name,
              physical_name: word.physical_name,
              type: word.type,
              constraint: '',
              default_value: '',
              auto_increment: '',
              foreign_key: true,
              not_null: '',
              primary_key: '',
              unique_key: '',
              character_set: '',
              collation: '',
              relation: relationId,
              referenced_column: columns[i].querySelector('id').innerHTML
            })
            targetTable.querySelector("columns").append(columDom.children[0])
          }
        }
        if (haveKey) {
          let edgeDom = this.xmlFile.xml.createElement("dom");
          edgeDom.innerHTML = ermUtils.creatEdgeContent({
            id: relationId,
            sourceId: sourceId,
            targetId: targetId
          })
          targetTable.querySelector('connections').append(edgeDom.children[0])
        } else {
          alert('源表需要主键')
        }

        this.loadXml(this.xmlFile.xml, true)
      });

      this.graph.connectionHandler.constraintHandler.createHighlightShape = function () {
        return new mxEllipse(null, this.highlightColor, this.highlightColor, 2);
      };
    },
    //显示隐藏加载框
    showLoadingFun(show) {
      var _this = this;
      if (show) {
        _this.showLoading = true;
        _this.showLoadingOpacity = 1;
      } else {
        _this.showLoadingOpacity = 0;
        setTimeout(function () {
          _this.showLoading = false;
        }, 800);
      }
    },
    //初始化缩放工具栏事件
    initToolPane() {
      var canvas = document.querySelector(".chart-wrap");
      var maxW;
      //获取元素
      var dv = document.querySelector("#" + this.graphId + " .resize-div");
      var x = 0;
      var w = 0;
      var isDown = false;
      var _this = this;
      //鼠标按下事件
      dv.onmousedown = function (e) {
        //获取x坐标和y坐标
        x = e.clientX;
        w = _this.leftToolPaneWidth;
        //开关打开
        isDown = true;
        //设置样式
        //dv.style.cursor = 'move';
        maxW = canvas.offsetWidth - 32;
      };
      //鼠标移动
      window.onmousemove = function (e) {
        if (isDown == false) {
          return;
        }
        //获取x和y
        var nx = e.clientX;
        let newW = nx - x + w;
        //不能太窄
        if (newW < 450) return;
        //不能太宽
        if (newW >= maxW) return;
        _this.leftToolPaneWidth = newW;
      };
      //鼠标抬起事件
      window.onmouseup = function () {
        //开关关闭
        isDown = false;
      };
    },
    //删除元素
    removeCells(cells) {
      let deleteDoms = []//待删除的节点
      //遍历被删除的节点
      for (let i = 0; i < cells.length; i++) {
        let cell = cells[i]
        if (cell.edge) {
          //如果是线条
          let target = cell.target
          let targetTableIndex = this.tableIndexMap.get(target.id).index
          let targetTable = this.xmlFile.xml.querySelector('contents').children[targetTableIndex]
          let connections = targetTable.querySelector('connections').children
          let columns = targetTable.querySelector('columns').children
          //遍历目标节点的全部线条
          for (let i = 0; i < connections.length; i++) {
            let relation = connections[i]
            if (relation.querySelector('id').innerHTML == cell.id) {
              //找到这个线条 然后遍历字段拿到对应的外键
              for (let i = 0; i < columns.length; i++) {
                let column = columns[i]
                if (column.querySelector('relation') && column.querySelector('relation').innerHTML == cell.id) {
                  deleteDoms.push(column)
                  break
                }
              }
              deleteDoms.push(relation)
              break
            }
          }
        } else if (cell.title == '表') {
          let tableIndex = this.tableIndexMap.get(cell.id).index
          let table = this.xmlFile.xml.querySelector('contents').children[tableIndex]
          deleteDoms.push(table)
        } else if (cell.title == '笔记') {
          let noteIndex = this.noteIndexMap.get(cell.id).index
          let note = this.xmlFile.xml.querySelector('contents').children[noteIndex]
          deleteDoms.push(note)
        }
      }
      for (let i = 0; i < deleteDoms.length; i++) {
        deleteDoms[i].parentNode.removeChild(deleteDoms[i]);
      }
      this.loadXml(this.xmlFile.xml, true)
      this.$emit("change-file-status", true);
    },
    //添加一个画布 back 添加完成以后回调
    initGraph(back) {
      let _this = this;
      _this.graph = this.$refs.graphEditor.init();
      if (_this.R.isNil(_this.graph)) {
        return;
      }
      _this.graph.setCellsEditable(false);
      _this.graph.setDropEnabled(true);
      _this.graph.setHtmlLabels(true);
      _this.initConnectStyle();
      _this.makeToolbarDraggable();
      //移动
      _this.graph.addListener(mxEvent.CELLS_MOVED, (sender, evt) => {
        let cells = evt.getProperty("cells");
        for (let i = 0; i < cells.length; i++) {
          let cell = cells[i]
          if (cell && cell.title == "表") {
            let table = this.xmlFile.xml.querySelector('contents').children[this.tableIndexMap.get(cell.id).index]
            table.querySelector('height').innerHTML = cell.geometry.height
            table.querySelector('width').innerHTML = cell.geometry.width
            table.querySelector('x').innerHTML = cell.geometry.x
            table.querySelector('y').innerHTML = cell.geometry.y
          } else if (cell && cell.title == "笔记") {
            let note = this.xmlFile.xml.querySelector('contents').children[this.noteIndexMap.get(cell.id).index]
            note.querySelector('height').innerHTML = cell.geometry.height
            note.querySelector('width').innerHTML = cell.geometry.width
            note.querySelector('x').innerHTML = cell.geometry.x
            note.querySelector('y').innerHTML = cell.geometry.y
          }
        }
      })

      //捕获任务节点的鼠标点击事件
      _this.graph.addListener(mxEvent.DOUBLE_CLICK, (sender, evt) => {
        _this.hideRigthMenuFun();
        var cell = evt.getProperty("cell");
        //点击线条
        if (cell && cell.edge) {
        }
        //点击表
        else if (cell && cell.title == "表") {
          _this.showToolName = "table-column";
          var dataIndex = _this.cellIdToTableDataIndexMap.get(cell.id);
          var table = _this.tableDataArray[dataIndex];
          _this.showTableColums = table.items;
          _this.editTableIndex = dataIndex;
          //_this.tableDetailType = "attribute";
          _this.editTableInfo.logical_name = table.name;
          _this.editTableInfo.physical_name = table.physical_name;
          if (table.description) {
            var obj = eval("(" + table.description + ")");
            _this.editTableInfo.description = JSON.stringify(obj, null, 4);
          } else {
            _this.editTableInfo.description = "";
          }
        } //点笔记
        else if (cell && cell.title == "笔记") {
          _this.noteIndex = _this.cellIdToNoteDataIndexMap.get(cell.id);
          _this.editNoteModal.show = true;
          _this.editNoteModal.id = _this.noteDataArray[_this.noteIndex].id;
          _this.editNoteModal.index = _this.noteIndex;
          _this.editNoteModal.text = _this.noteDataArray[_this.noteIndex].text;
          _this.editNoteModal.left = evt.properties.event.pageX;
          _this.editNoteModal.top = evt.properties.event.pageY;
        } else {
          _this.showToolName = "";
        }
      });

      //捕获任务节点的鼠标点击事件
      _this.graph.addListener(mxEvent.CLICK, function (sender, evt) {
        _this.hideRigthMenuFun();
        var cell = evt.getProperty("cell");
        //点击线条
        if (cell && cell.edge) {
        }
        //点击表
        if (
          cell &&
          cell.title == "表" &&
          (_this.showToolName == "table-column" ||
            _this.showToolName == "table")
        ) {
          if (_this.showToolName == "table") {
            _this.showToolName = "table-column";
          }
          var dataIndex = _this.cellIdToTableDataIndexMap.get(cell.id);
          var table = _this.tableDataArray[dataIndex];
          _this.editTableIndex = dataIndex;
          _this.showTableColums = table.items;
         // _this.tableDetailType = "attribute";
          _this.editTableInfo.logical_name = table.name;
          _this.editTableInfo.physical_name = table.physical_name;
          if (table.description) {
            var obj = eval("(" + table.description + ")");
            _this.editTableInfo.description = JSON.stringify(obj, null, 4);
          } else {
            _this.editTableInfo.description = "";
          }
        }
      });
      _this.initToolPane();
      //_this.graph.zoomTo(0.8); //在缩放一半，否则是满屏状态，不好看
      setTimeout(() => {
        var graphContainer = document.querySelector(
          "#" + this.graphId + " .graphContainer svg"
        );
        _this.showLoadingFun(false);
        if (!graphContainer) {
          return;
        }
        var x = parseInt(graphContainer.style.minWidth.replace("px", "")) / 3;
        var y = parseInt(graphContainer.style.minHeight.replace("px", "")) / 3;
        _this.graph.panGraph(-x, -y);
        if (back) {
          back();
        }
      }, 100);
    },
    //选中某属性
    choiceColum(index) {
      this.rightMenu = {
        from: index,
        columIndex: index,
      };
    },
    //隐藏右键菜单
    hideRigthMenuFun() {
      this.rightMenu.from = -1;
      this.rightMenu.show = false;
    },
    //显示右键菜单
    showRigthMenuFun(e, from) {
      this.rightMenu.from = from;
      this.rightMenu.columIndex = from;
      this.rightMenu.show = true;
      this.rightMenu.left = e.pageX + "px";
      this.rightMenu.top = e.pageY - 20 + "px";
    },
    //初始化拖拽编辑框事件
    initEditNoteModalMouseEvent() {
      var _this = this;
      //获取元素
      var dv = document.querySelector(
        "#" + this.graphId + " .edit-note-modal .title-move"
      );
      var x = 0;
      var y = 0;
      var l = 0;
      var t = 0;
      var isDown = false;
      //鼠标按下事件
      dv.onmousedown = function (e) {
        //获取x坐标和y坐标
        x = e.clientX;
        y = e.clientY;

        //获取左部和顶部的偏移量
        l = _this.editNoteModal.left;
        t = _this.editNoteModal.top;
        //开关打开
        isDown = true;
        //设置样式
        dv.style.cursor = "move";
        //鼠标移动
        document.onmousemove = function (e) {
          e.preventDefault();
          if (isDown == false) {
            document.onmousemove = null
            return;
          }
          //获取x和y
          var nx = e.clientX;
          var ny = e.clientY;
          //计算移动后的左偏移量和顶部的偏移量
          var nl = nx - (x - l);
          var nt = ny - (y - t);
          _this.editNoteModal.left = nl;
          _this.editNoteModal.top = nt;
        };
      };

      //鼠标抬起事件
      dv.onmouseup = function () {
        //开关关闭
        isDown = false;
        dv.style.cursor = "default";
        document.onmousemove = null
      };
    },
    //保存文件
    saveFile(saveAs) {
      let _this = this;
      if (!ipcRenderer) {
        if (!this.xmlFile.xml) return;
        if (!this.xmlFile.name) {
          Swal.fire({
            input: "text",
            inputValue: 'new_ERM.erm',
            inputPlaceholder: "请输入文件名",
            inputAttributes: {
              autocapitalize: "off",
            },
            showCancelButton: true,
            cancelButtonText: '取消',
            confirmButtonText: "保存",
            showLoaderOnConfirm: true,
          }).then((result) => {
            if (result.isConfirmed && result.value) {
              this.xmlFile.name = result.value;
              this.saveFile(saveAs)
            }
          });
          return
        }

        function fakeClick(obj) {
          var ev = document.createEvent("MouseEvents");
          ev.initMouseEvent(
            "click",
            true,
            false,
            window,
            0,
            0,
            0,
            0,
            0,
            false,
            false,
            false,
            false,
            0,
            null
          );
          obj.dispatchEvent(ev);
          _this.$emit("change-file-status", false);
        }
        function exportRaw(name, data) {
          var urlObject = window.URL || window.webkitURL || window;
          var export_blob = new Blob([data]);
          var save_link = document.createElementNS(
            "http://www.w3.org/1999/xhtml",
            "a"
          );
          save_link.href = urlObject.createObjectURL(export_blob);
          save_link.download = name;
          fakeClick(save_link);
        }
        exportRaw(
          this.xmlFile.name,
          new XMLSerializer().serializeToString(this.xmlFile.xml)
        );
      } else {
        let xml = new XMLSerializer().serializeToString(this.xmlFile.xml)
        if (!this.xmlFile.name) {
          this.xmlFile.name = 'new_ERM.erm'
        }
        ipcRenderer.send('save-file', {
          path: this.xmlFile.path,
          name: this.xmlFile.name,
          data: xml,
          id: this.graphId,
          saveAs: saveAs
        })
        this.$emit("change-file-status", false);
      }
    },
  },
  mounted() {
    let _this = this;
    var dropbox = document.getElementById(this.graphId);
    dropbox.addEventListener("drop", this.enentDrop, false);
    dropbox.addEventListener("dragleave", function (e) {
      e.stopPropagation();
      e.preventDefault();
    });
    dropbox.addEventListener("dragenter", function (e) {
      e.stopPropagation();
      e.preventDefault();
    });
    dropbox.addEventListener("dragover", function (e) {
      e.stopPropagation();
      e.preventDefault();
    });
    //查找按钮
    document.getElementById(this.graphId).onkeydown = function (e) {
      _this.rightMenu.show = false;
      var keyCode = e.keyCode || e.which || e.charCode;
      var ctrlKey = e.ctrlKey || e.metaKey;
      if (ctrlKey && keyCode == 70) {
        _this.showFindModal = true;
        setTimeout(() => {
          var findInput = document.getElementById("findInput" + this.graphId);
          findInput.focus();
          findInput.select();
        }, 500);
      }
    };
    document.getElementById(this.graphId).onclick = (e) => {
      this.hideRigthMenuFun();
    };
    //菜单右键
    document.querySelector(
      "#" + this.graphId + " .table-attribute"
    ).oncontextmenu = (e) => {
      e.preventDefault();
      let index = "-1";
      index = e.target.getAttribute("index");
      this.showRigthMenuFun(e, index);
    };
    this.initGraph();
    this.initEditNoteModalMouseEvent();

    let xmlDoc
    if (window.DOMParser) {
      var parser = new DOMParser();
      xmlDoc = parser.parseFromString(ermUtils.getErmXml(), "text/xml");
    } else {
      //IE
      xmlDoc = new ActiveXObject("Microsoft.XMLDOM");
      xmlDoc.async = "false";
      xmlDoc.loadXML(ermUtils.getErmXml());
    }
    _this.loadXml(xmlDoc);
    _this.xmlFile = {
      xml: xmlDoc,
      name: "",
    };


    if (ipcRenderer) {
      ipcRenderer.on('save-file-back-' + this.graphId, (e, path) => {
        if (path) {
          path = path.replaceAll('\\', '/')
          this.xmlFile.path = path.substring(0, path.lastIndexOf('/'))
          this.xmlFile.name = path.substring(path.lastIndexOf('/') + 1)

          this.$emit("change-file-name", this.xmlFile.name);
        }
      })
    }

  },
};
</script>

<style lang="less">
.graph-index {
  display: flex;
  .message {
    width: 300px;
    text-align: center;
    left: calc(50% - 150px);
    position: fixed;
    z-index: 9999;
    background: #fddaa6;
    padding: 0px 20px;
    line-height: 2rem;
    box-shadow: 0 0 6px #999;
    border-radius: 4px;
    opacity: 1;
  }
  .edit-note-modal {
    transition: none;
    position: absolute;
    width: 400px;
    background: #ffffff;
    box-shadow: 0 0 8px rgba(0, 0, 0, 0.6);
    z-index: 99;
    .title {
      display: flex;
      padding: 10px;
      background: #cea8e3;
      span {
        font-size: 0.8rem;
        flex: 1;
        color: #333333;
      }
      .fa-close:hover {
        color: #333333;
      }
      .fa-check:hover {
        color: #3498db;
      }
    }
    textarea {
      transition: none;
      box-sizing: border-box;
      padding: 10px;
      outline: none;
      border: none;
      width: 100%;
      height: 200px;
      resize: vertical;
    }
  }
  .rigth-menu {
    font-size: 0.8rem;
    border-radius: 2px;
    z-index: 9999999;
    position: fixed;
    left: 0;
    top: 0;
    background: #ffffff;
    padding: 6px;
    box-shadow: 0 0 8px rgba(0, 0, 0, 0.3);
    .item {
      margin: 6px 4px;
      cursor: pointer;
      span {
        margin-left: 4px;
      }
    }
    .item:hover {
      span,
      i {
        color: #3498db;
      }
    }
  }
  .node-show-botton {
    width: 2rem;
    height: 2rem;
    text-align: center;
    border-radius: 2rem;
    background: #e67e22;
    position: absolute;
    box-shadow: 2px 2px 4px #7e7e7e;
    right: 15px;
    top: 10px;
    z-index: 99;

    i {
      line-height: 2rem;
      cursor: pointer;
      color: #ffffff;
      font-size: 1rem;
    }
  }

  .node-show-botton:hover {
    box-shadow: 2px 2px 6px #5a5a5a;
  }

  .left-pane {
    transition: none;
    position: absolute;
    left: 2rem;
    top: 0;
    width: 300px;
    height: 100%;
    display: block;
    z-index: 999;
    display: flex;

    .resize {
      width: 4px;
      height: 100%;
      cursor: w-resize;
      background: transparent;
    }
    .resize:hover {
      background: rgba(0, 0, 0, 0.1);
    }

    .tool-plane {
      font-size: 0.8rem;
      display: flex;
      flex-direction: column;
      box-sizing: border-box;
      transition: all 0.2s ease-in-out;
      width: 100%;
      height: 100%;
      background: #ffffff;
      box-shadow: 2px 0 4px #bfbfbf;

      border-left: 1px #e1e7eb solid;

      .title {
        display: flex;
        margin: 10px;

        span {
          font-weight: bold;
          color: #2c3e50;
        }
      }
    }
  }

  .info-plane {
    .tab {
      padding: 10px;

      span {
        margin-right: 10px;
        cursor: pointer;
        border-bottom: 2px transparent solid;
      }

      span:hover,
      .actived {
        color: #3498db;
      }

      .actived {
        border-bottom: 2px #3498db solid;
      }
    }

    .colum-item {
      display: flex;
      padding: 6px 10px;

      input {
        border: 1px #e7e7e7 solid;
        outline: none;
      }

      input:focus {
        border: 1px #bcc1c8 solid;
        outline: none;
      }

      .button {
        border-radius: 2px;
        cursor: pointer;
        padding: 4px 10px;
        background: #eeeeee;
        border: 1px transparent solid;
      }

      .button:hover {
        background: #e6f3ff;
        border: 1px #8db7db solid;
      }
    }

    .colum-item.value:hover {
      background: #ecf0f1;
    }
  }
  .colum-list {
    height: 100%;
    padding: 0 !important;
    .table-detail-rigth {
      height: 100%;
      flex: 1;
      overflow: auto;
      .table-remark {
        transition: none;
        width: 100%;
        margin: 0px;
        padding: 10px;
        box-sizing: border-box;
        height: calc(100% - 28px);
        overflow-y: auto;
        resize: none;
        border: 1px #eee solid;
        outline: none;
      }
      .table-remark:focus {
        outline: none;
      }
    }
    .table-detail-rigth.edit {
      .item {
        margin: 6px 4px;
        display: flex;
        label {
          padding: 2px 0px;
          display: inline-block;
          width: 3rem;
          text-align-last: justify;
          text-align: justify;
          margin-right: 4px;
        }
        .flex1,
        select,
        .input {
          padding: 2px 4px;
          outline: none;
          margin: 0;
        }
        .flex1,
        select {
          border: 1px rgba(0, 0, 0, 0.1) solid;
          flex: 1;
        }
        textarea {
          transition: none;
          min-height: 200px;
          resize: vertical;
        }
      }

      .word-select {
        overflow: auto;
        display: block;
        position: relative;
        max-height: 300px;
        width: calc(100% - 4.4rem);
        margin-left: 4rem;
        box-shadow: 0 0 4px #eee;
        padding: 0;
        .word {
          cursor: pointer;
          padding: 4px 6px;
        }
        .word:hover {
          background: #d2dfe9;
        }
      }
    }
    .table-detail-left {
      padding: 2px 0;
      background: #eee;
      .item {
        padding: 6px 8px;
        cursor: pointer;
      }
      .actived,
      .item:hover {
        background: #fff;
      }
    }
    .colum-item {
      padding: 6px 10px;
      display: flex;

      div {
        word-break: break-all;
        box-sizing: border-box;
        width: 0;
        padding: 2px;
      }
      input {
        display: inline;
        width: 100%;
        border: none;
        background: none;
        outline: none;
      }
    }

    .colum-item:hover,
    .colum-item.actived {
      background: #ecf0f1;
      color: #3498db;
    }
  }

  .table-list {
    .table-item {
      float: left;
      padding: 6px 10px;

      .fa-map-marker {
        line-height: 1rem;
        cursor: pointer;
      }

      .fa-map-marker:hover {
        color: #3498db;
      }
      span {
        cursor: pointer;
      }
      span:hover {
        color: #3498db;
      }
    }
  }

  .note-list {
    .node-item {
      word-break: break-all;
      color: #34495e;
      background: #ecf0f1;
      padding: 15px 10px;
      margin: 10px;
      border-radius: 2px;
      border-bottom-left-radius: 20px;
      float: left;
      textarea {
        transition: none;
        position: relative;
        border: none;
        background: none;
        width: 100%;
        height: 100%;
        resize: none;
        outline: none;
      }
    }
  }

  .chart-palette {
    display: flex;
    flex-direction: column;
    z-index: 99;
    box-shadow: 2px 0px 6px #bfbfbf;
    width: 2rem;
    background-color: white;

    .tool-items {
      padding: 0 !important;
      flex: 1;
      border-right: 1px solid #efefef;

      .tool-item {
        cursor: move;
        line-height: 2rem;
        text-align: center;
        margin: 0;
        height: 2rem;
        width: 2rem;
      }
    }

    .choice-file,
    .bottom-tools .item {
      line-height: 2rem;
      cursor: pointer;
      text-align: center;
    }

    .choice-file:hover,
    .tool-item:hover,
    .tool-item.actived,
    .bottom-tools .item:hover,
    .bottom-tools .item.actived {
      background: #f1f2f3;

      i {
        color: #3498db;
      }
    }

    .bottom-tools {
      border-top: 1px #bdc3c7 solid;
    }
  }

  .table {
    width: 100%;
    height: 100%;
    padding: 4px;
    box-sizing: border-box;

    .table-info {
      flex-direction: column;
      width: 100%;
      height: 100%;
      display: flex;
      border-radius: 4px;
      background: #ffffff;
      box-shadow: 0 0 4px #b3b3b3;
      padding: 10px;
      box-sizing: border-box;

      .title {
        overflow: hidden;
        width: 100%;
        line-height: 1.4rem;
        text-align: center;
        font-size: 0.9rem;
        font-weight: bold;
        color: #2c3e50;
      }

      .items {
        flex: 1;
        overflow: auto;
      }

      .item {
        display: flex;
        margin-top: 5px;
        font-size: 0.8rem;
        line-height: 1.2rem;

        .text {
          //font-weight: bold;
          color: #526980;
        }
      }
    }
  }

  .note {
    color: #2c3e50;
    white-space: normal;
    text-align: left;
    line-height: 1.2rem;
    box-sizing: border-box;
    width: 100%;
    height: 100%;
    padding: 16px;
    background: linear-gradient(225deg, transparent 6px, #cea8e3 0);
    position: relative;
  }

  .note::after {
    content: '';
    position: absolute;
    right: 0px;
    top: 0px;
    background: linear-gradient(-135deg, transparent 50%, #cea8e3 0);
    width: 10px;
    height: 10px;
    border-bottom-left-radius: 0px;
    box-shadow: -0.2em 0.2em 0.2em #ab8cbd;
  }

  .find-modal {
    padding: 0 10px;
    display: flex;
    position: fixed;
    right: 4rem;
    top: 4rem;
    width: 20rem;
    height: 2rem;
    z-index: 999999999;
    background: #ffffff;
    box-shadow: 0 0 6px rgba(0, 0, 0, 0.3);
    border-radius: 4px;
    input {
      flex: 1;
      outline: none;
      margin: 0;
      padding: 0 4px;
      border: none;
      height: 100%;
    }
    i {
      color: #bdc3c7;
      cursor: pointer;
      margin: 0 4px;
      line-height: 1.9rem;
    }
    i:hover {
      color: #7f8c8d;
    }
  }

  .loading {
    transition: all 1s ease-in-out;
    left: 0;
    top: 0;
    z-index: 999999;
    background: rgba(0, 0, 0, 0.7);
    position: absolute;
    width: 100%;
    height: 100%;

    .icon {
      text-align: center;
      position: relative;
      top: 50%;

      i {
        animation: turn 1s linear infinite;
        font-size: 2rem;
        color: #3498db;
      }

      p {
        margin-top: 10px;
        color: #dbdbdb;
      }
    }
  }
}
</style>
